package org.example.osproject01;

import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.chart.LineChart;
import javafx.scene.control.*;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.input.MouseEvent;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import org.example.osproject01.Object.Item;
import org.example.osproject01.Object.Job;
import org.example.osproject01.Object.LineChartUtils;

import static org.example.osproject01.HelloApplication.STAGE;
import static org.example.osproject01.Object.PublicResource.*;

public class HelloController {

    public Button addToInput;
    public Button deleteInputJob;
    public Button updateInputJob;
    public Button reflash;
    public Button workBegin;
    public Button workEnd;

    public Button reflash2;
    public Button runBegin;
    public Button stopRun;

    public TableView<Item> poolList = new TableView<>();
    public TableView<Item> inputList = new TableView<>();
    public TableView<Item> poolList2 = new TableView<>();
    public TableView<Item> readyList = new TableView<>();
    public TableView<Item> readyList2 = new TableView<>();
    public TableView<Item> history = new TableView<>();

    public Text small;
    public Text perTime;
    public Text clock;
    public Text clock2;
    public Text workAl;
    public Text workAl2;

    public CheckBox Check2;

    public LineChart runingWork;
    public ProgressBar pro1;
    public ProgressBar pro2;
    LineChartUtils lineChart;

    @FXML
    private ChoiceBox<String> choiceBox1, choiceBox2;

    public static int Timepian;
    public int nowWorkNum;
    public int CUPStatue;

    private Boolean suspended = false;
    private Boolean suspended2 = false;

    private Item nowWork;

    private String[] process = {"先来先服务", "短进程优先", "高响应比优先", "优先级调度", "时间片轮转", "多级反馈队列"};

    private String[] work = {"先来先服务(FCFS)", "短作业优先(SJF)", "高响应比优先(PSA)", "优先级调度(HRRN)"};

    @FXML
    public void initialize() {
        choiceBox1.getItems().addAll(process);
        choiceBox1.getSelectionModel().select(0);

        choiceBox2.getItems().addAll(work);
        choiceBox2.getSelectionModel().select(0);

        addColumn(inputList);
        addColumn(poolList);
        addColumn(poolList2);
        addColumn(readyList);
        addColumn(readyList2);
        addColumn(history);

        lineChart = new LineChartUtils(runingWork);

        Timepian = 1000;
        nowWorkNum = 1;

        pro1.setProgress((double)(allBlock - spaceBlock)/allBlock);
        pro2.setProgress((double)(allTape - spaceTape)/allTape);

        CUPStatue=0;

        preInputQueue.add(new Job( "JOB1","25","15","2","10","0"));
        preInputQueue.add(new Job( "JOB2","30","60","1","10","20"));
        preInputQueue.add(new Job( "JOB3","10","50","3","10","30"));
        preInputQueue.add(new Job( "JOB4","20","10","2","10","35"));
        preInputQueue.add(new Job( "JOB5","15","30","2","10","40"));
    }


    @FXML
    public void onExit(MouseEvent mouseEvent) {
        // 退出
        System.exit(0);
    }

    @FXML
    public void endWork(MouseEvent mouseEvent) {
        // 设置暂停状态
        suspended=false;
    }

    @FXML
    public void beginWork(MouseEvent mouseEvent) throws InterruptedException {
        suspended=true;
        new Thread(() -> {
            while (suspended) {
                timer++;
                Platform.runLater(() -> {
                    clock.setText("" + timer);
                });
                pro1.setProgress((double)(allBlock - spaceBlock)/allBlock);
                // 开始作业调度
                if (choiceBox2.getSelectionModel().getSelectedIndex() == 0) {
                    // 先来先服务
                    nowWork = getFCFSItemFromPool(poolList2);
                    jobScheduling();

                } else if (choiceBox2.getSelectionModel().getSelectedIndex() == 1) {
                    // 短作业优先
                    nowWork = getSJFItemFromPool(poolList2);
                    jobScheduling();

                } else if (choiceBox2.getSelectionModel().getSelectedIndex() == 2) {
                    // 优先级调度
                    nowWork = getSJFItemFromPool(poolList2);
                    jobScheduling();

                } else if (choiceBox2.getSelectionModel().getSelectedIndex() == 3) {
                    // 相应比
                    HRRN();

                }
                try {
                    Thread.sleep(1000); // 暂停 1 秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        System.out.println("开始作业调度");
    }

    public void onBeginRun(MouseEvent mouseEvent) {
        suspended2=true;
        new Thread(() -> {
            while (suspended2) {
                if(readyList2==null) {
                    suspended2 = false;
                    break;
                }
                Platform.runLater(() -> clock2.setText("" + timer2));
                if(CUPStatue==1){
                    Platform.runLater(() -> lineChart.addData(""+timer2,nowWorkNum));
                    timer2++;
                    pro2.setProgress((double)(allTape - spaceTape)/allTape);
                }
                // 开始作业调度
                if (choiceBox1.getSelectionModel().getSelectedIndex() == 0) {
                    // 先来先服务
                    nowWork = getFCFSItemFromPool(readyList2);
                    CPUScheduling();
                } else if (choiceBox1.getSelectionModel().getSelectedIndex() == 1) {
                    // 短作业优先
                    nowWork = getSJFItemFromPool(readyList2);
                    CPUScheduling();

                } else if (choiceBox1.getSelectionModel().getSelectedIndex() == 2) {
                    // 优先级调度
                    nowWork = getPSAItemFromPool(poolList2);
                    CPUScheduling();

                } else if (choiceBox1.getSelectionModel().getSelectedIndex() == 3) {
                    // 高相应比
                    HRRN();
                }
                System.out.println("磁带："+spaceTape);
                try {
                    Thread.sleep(100); // 暂停 1 秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public void onStopRun(MouseEvent mouseEvent) {
        suspended2=false;
    }


    private void jobScheduling() {
        if(nowWork==null){
            return;
        }
        if(spaceBlock>Integer.parseInt((nowWork.getNeedSpace()))){
            spaceBlock-=Integer.parseInt((nowWork.getNeedSpace()));
            nowWork.setSpaceStatus("已分配内存");
            nowWork.setRunStatus("准备就绪");
            poolList2.getItems().remove(nowWork);
            readyList.getItems().add(nowWork);
        }else{
            nowWork.setSpaceStatus("内存不足");
            nowWork.setRunStatus("等待内存");
        }
    }

    private void CPUScheduling() {
        if(nowWork==null){
            CUPStatue=0;
            return;
        }
        if(spaceTape*2>Integer.parseInt(nowWork.getNeedTape())){
            CUPStatue=1;
            if(nowWork.getRunStatus().equals("准备就绪")) {
                spaceTape -= Integer.parseInt(nowWork.getNeedTape());
            }
            nowWork.setRunStatus("正在运行");
            nowWork.setRunTime(String.valueOf((Integer.parseInt(nowWork.getRunTime())-1)));
            if(Integer.parseInt(nowWork.getRunTime())<=0){
                nowWorkNum++;
                readyList2.getItems().remove(nowWork);

                history.getItems().add(nowWork);
                setStatus(nowWork);
                nowWork.setRunStatus("运行完成");
                spaceTape+=Integer.parseInt(nowWork.getNeedTape());
                spaceBlock+=Integer.parseInt((nowWork.getNeedSpace()));
                CUPStatue=0;
                timer2++;
            }
            System.out.println(nowWork);
        }
        else{
            CUPStatue=0;
            nowWork.setRunStatus("磁带不足");
        }
    }

    private void setStatus(Item nowWork) {
        nowWork.setRunStatus("已完成");
        nowWork.setSpaceStatus("已运行完成");
        nowWork.setFinishTime(String.valueOf(timer2+1));
        nowWork.setRunTime(nowWork.getRrunTime());
        nowWork.setCyclingTime(Integer.parseInt(nowWork.getRrunTime())+Integer.parseInt(nowWork.getSubmitTime())+"");
    }

    private void HRRN() {

    }

    public Item getFCFSItemFromPool(TableView<Item> tableView) {
        ObservableList<Item> items = tableView.getItems();

        if (items.isEmpty()) {
            return null;
        }

        Item minItem = items.get(0);
        int minSubmitTime = Integer.parseInt(minItem.getSubmitTime());

        for (Item item : items) {
            int currentSubmitTime = Integer.parseInt(item.getSubmitTime());
            if (minSubmitTime > currentSubmitTime) {
                minSubmitTime = currentSubmitTime;
                minItem = item;
            }
        }
        System.out.println(minSubmitTime);
        return minItem;
    }
    public Item getSJFItemFromPool(TableView<Item> tableView) {
        ObservableList<Item> items = tableView.getItems();

        if (items.isEmpty()) {
            System.out.println("表格为空，没有可比较的行。");
            return null;
        }

        Item minItem = items.get(0);
        int minNeedSpace = Integer.parseInt(minItem.getNeedSpace());

        for (Item item : items) {
            int currentNeedSpace = Integer.parseInt(item.getNeedSpace());
            if (minNeedSpace > currentNeedSpace) {
                minNeedSpace = currentNeedSpace;
                minItem = item;
            }
        }
        System.out.println(minNeedSpace);
        return minItem;
    }

    private Item getPSAItemFromPool(TableView tableView) {
        ObservableList<Item> items = tableView.getItems();
        if (items.isEmpty()) {
            return null;
        }

        Item minItem = items.get(0);
        int minPriority = Integer.parseInt(minItem.getPriority());

        for (Item item : items) {
            int currentPriority = Integer.parseInt(item.getPriority());
            if (minPriority > currentPriority) {
                minPriority = currentPriority;
                minItem = item;
            }
        }
        System.out.println(minPriority);
        return minItem;
    }


    @FXML
    public void onRefresh() {
        ObservableList data = poolList.getItems();
        poolList2.setItems(FXCollections.observableArrayList(data));
        clock.setText("" + timer);
        perTime.setText(1000+"ms");
        String temp = work[choiceBox2.getSelectionModel().getSelectedIndex()];
        workAl.setText(temp);
        poolList.getItems().clear();
    }
    @FXML
    public void onRefresh2() {
        ObservableList data = readyList.getItems();
        readyList2.setItems(FXCollections.observableArrayList(data));
        clock2.setText("" + timer2);
        //perTime.setText("" + timer);
        String temp = work[choiceBox1.getSelectionModel().getSelectedIndex()];
        if(Check2.isSelected()){
            temp+=" 可抢占";
        }else{
            temp+=" 不可抢占";
        }
        workAl2.setText(temp);
        readyList.getItems().clear();
    }

    @FXML
    public void onSmall() {
        //最小化
        STAGE.setIconified(true);
    }

    @FXML
    public void onAddToInput(MouseEvent mouseEvent) throws Exception {
        new JobInputDialog().start(new Stage());
    }

    public void updateInputList() {
        inputList.getItems().clear();
        for (Job job : preInputQueue) {
            inputList.getItems().addAll(job.toItem());
        }
    }

    public void submitOne() {
        if (inputList.getSelectionModel().getSelectedItem() != null && !inputList.getItems().isEmpty()) {
            System.out.println(inputList.getSelectionModel().getFocusedIndex());
            poolList.getItems().addAll(inputList.getSelectionModel().getSelectedItem());
            inputList.getItems().remove(inputList.getSelectionModel().getSelectedItem());
            preInputQueue.remove(inputList.getSelectionModel().getFocusedIndex() + 1);
        }
    }

    public void submitAll() {
        if (inputList.getSelectionModel().getSelectedItem() != null && !inputList.getItems().isEmpty()) {
            for (Job job : preInputQueue) {
                poolList.getItems().addAll(job.toItem());
            }
            preInputQueue.clear();
            inputList.getItems().clear();
        }
    }

    public void removeInputItem() {
        inputList.getItems().remove(inputList.getSelectionModel().getSelectedItem());
        preInputQueue.remove(inputList.getSelectionModel().getFocusedIndex());
    }

    public void addColumn(TableView<Item> inputList) {
        TableColumn<Item, String> uuidItem = new TableColumn<>("ID");
        uuidItem.setCellValueFactory(cellData -> cellData.getValue().idProperty());

        TableColumn<Item, String> nameItem = new TableColumn<>("名字");
        nameItem.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
        nameItem.setCellFactory(TextFieldTableCell.forTableColumn());

        TableColumn<Item, String> submitTimeItem = new TableColumn<>("提交时间");
        submitTimeItem.setCellValueFactory(cellData -> cellData.getValue().submitTimeProperty());

        TableColumn<Item, String> runTimeItem = new TableColumn<>("运行时间");
        runTimeItem.setCellValueFactory(cellData -> cellData.getValue().runTimeProperty());

        TableColumn<Item, String> cyclingTimeItem = new TableColumn<>("周转时间");
        cyclingTimeItem.setCellValueFactory(cellData -> cellData.getValue().cyclingTimeProperty());

        TableColumn<Item, String> weightedTimeItem = new TableColumn<>("平均周转");
        weightedTimeItem.setCellValueFactory(cellData -> cellData.getValue().cyclingTimeProperty());

        TableColumn<Item, String> finishTimeItem = new TableColumn<>("结束时间");
        finishTimeItem.setCellValueFactory(cellData -> cellData.getValue().finishTimeProperty());

        TableColumn<Item, String> runStatusItem = new TableColumn<>("运行状态");
        runStatusItem.setCellValueFactory(cellData -> cellData.getValue().runStatusProperty());

        TableColumn<Item, String> spaceStatusItem = new TableColumn<>("分配状态");
        spaceStatusItem.setCellValueFactory(cellData -> cellData.getValue().spaceStatusProperty());

        TableColumn<Item, String> needSpaceItem = new TableColumn<>("所需空间");
        needSpaceItem.setCellValueFactory(cellData -> cellData.getValue().needSpaceProperty());

        TableColumn<Item, String> atWhereItem = new TableColumn<>("所在位置");
        atWhereItem.setCellValueFactory(cellData -> cellData.getValue().atWhereProperty());

        TableColumn<Item, String> needTapeItem = new TableColumn<>("所需磁带");
        needTapeItem.setCellValueFactory(cellData -> cellData.getValue().needTapeProperty());

        TableColumn<Item, String> priorityItem = new TableColumn<>("优先级");
        priorityItem.setCellValueFactory(cellData -> cellData.getValue().priorityProperty());

        // 然后，将这些列添加到 TableView
        inputList.getColumns().addAll(uuidItem, nameItem, submitTimeItem, runTimeItem, cyclingTimeItem, weightedTimeItem, finishTimeItem, runStatusItem, spaceStatusItem, needSpaceItem, atWhereItem, needTapeItem, priorityItem);

        ObservableList<Item> data = FXCollections.observableArrayList();
        inputList.setItems(data);
    }
}